"""
@Author  : 康帅
@Time    : 2021/3/11 14:50
@Function: 状态模式(行为模式)
"""

# 导入封装的基类
from DesignMode.StateMode.WaterBaseClass import Context, State

"""
优点：
1.封装了状态的转换规则，在状态模式中可以将状态的转换代码封装在环境类中，对状态转换代码进行集中管理，而不是分散在一个个业务逻辑中
2.将所有与某个状态有关的行为放到一个类中（称为状态类），使开发人员只专注于该状态下的逻辑开发
3.允许状态转换逻辑与状态对象合为一体，使用时只需要注入一个不同的状态对象即可使环境对象拥有不同的行为

缺点：
1.会增加系统类和对象的个数
2.状态模式的结构与实现都较为复杂，如果使用不当容易导致程序结构和代码的混乱

状态模式应用场景：
1.一个对象的行为取决于它的状态，并且它在运行时可能经常改变它的状态，从而改变它的行为。
2.一个操作中含有庞大的多分支的条件语句，这些分支依赖于该对象的状态，且每一个分支的业务逻辑都非常复杂时，
我们可以使用状态模式来拆分不同的分支逻辑，使程序有更好的可读性和可维护性。
"""


class Water(Context):
    """ 水(H2O)"""

    def __init__(self):
        super().__init__()
        self.add_state(SolidState("固态"))
        self.add_state(LiquidState("液态"))
        self.add_state(GaseousState("气态"))
        self.set_temperature(25)

    def get_temperature(self):
        """ 获取温度 """

        return self._get_state_info()

    def set_temperature(self, temperature):
        """ 设置温度 """

        self._set_state_info(temperature)

    def rise_temperature(self, step):
        """ 温度上升 """

        self.set_temperature(self.get_temperature() + step)

    def reduce_temperature(self, step):
        """ 温度下降 """

        self.set_temperature(self.get_temperature() - step)

    def behavior(self):
        """ 不同的行为状态 """

        state = self.get_state()
        if isinstance(state, State):
            state.behavior(self)


# 单例装饰器
def singleton(cls, *args, **kwargs):
    """ 构造一个单例装饰器 """

    instance = {}

    def __singleton(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]

    return __singleton


@singleton
class SolidState(State):
    """ 固态状态 """

    def __init__(self, name):
        super().__init__(name)

    def is_match(self, state_info):
        return state_info < 0

    def behavior(self, context):
        print("我是固态，当前温度：" + str(context._get_state_info()) + "℃")


@singleton
class LiquidState(State):
    """ 液态状态 """

    def __init__(self, name):
        super().__init__(name)

    def is_match(self, state_info):
        return state_info >= 0 and state_info < 100

    def behavior(self, context):
        print("我是液态，当前温度：" + str(context._get_state_info()) + "℃")


@singleton
class GaseousState(State):
    """ 气态状态 """

    def __init__(self, name):
        super().__init__(name)

    def is_match(self, state_info):
        return state_info >= 100

    def behavior(self, context):
        print("我是气态，当前温度：" + str(context._get_state_info()) + "℃")


if __name__ == '__main__':
    water = Water()
    water.behavior()
    water.set_temperature(-4)
    water.behavior()
    water.rise_temperature(18)
    water.behavior()
    water.rise_temperature(110)
    water.behavior()
